main()
{
	//------------------
	//EFECTS DEFINITIONS
	//------------------
	
		qBarrels = false;
		precacheItem( "barrel_mp" );
		barrels = getentarray ("explodable_barrel","targetname");
		if ( (isdefined(barrels)) && (barrels.size > 0) )
			qBarrels = true;
		barrels = getentarray ("explodable_barrel","script_noteworthy");
		if ( (isdefined(barrels)) && (barrels.size > 0) )
			qBarrels = true;
		if (qBarrels)
		{
			level.breakables_fx["barrel"]["explode"] 	= loadfx ("props/barrelExp");
			level.breakables_fx["barrel"]["burn_start"]	= loadfx ("props/barrel_ignite");
			level.breakables_fx["barrel"]["burn"]	 	= loadfx ("props/barrel_fire_top");
		}
		oilspill = getentarray ("oil_spill","targetname");
		if(isdefined(oilspill) && oilspill.size > 0)
		{
			level.breakables_fx["oilspill"]["burn"]		= loadfx ("props/barrel_fire");	
			level.breakables_fx["oilspill"]["spark"]	= loadfx("impacts/small_metalhit_1"); 
		}
		
	//------------------
	//------------------
	
	
	//-----------------
	//SOUND DEFINITIONS
	//-----------------
		level.barrelExpSound = "explo_metal_rand";
	//-----------------
	//-----------------
	
		
		level.barrelHealth = 150;
		maxBrokenPieces = 25;
	//-------------
	//-------------
	
	level.precachemodeltype = [];
	level.barrelExplodingThisFrame = false;
	level.breakables_clip = [];
	
	temp = getentarray ("breakable clip","targetname");
	for (i=0;i<temp.size;i++)
		level.breakables_clip[level.breakables_clip.size] = temp[i];
	level._breakable_utility_modelarray = [];
	level._breakable_utility_modelindex = 0;
	level._breakable_utility_maxnum = maxBrokenPieces;
	common_scripts\utility::array_thread(getentarray ("explodable_barrel","targetname"), ::explodable_barrel_think);
	//common_scripts\utility::array_thread(getentarray ("explodable_barrel","script_noteworthy"), ::explodable_barrel_think); ASK MO
	common_scripts\utility::array_thread(getentarray ("oil_spill", "targetname"), ::oil_spill_think);
}

oil_spill_think()
{
	self.end = getstruct(self.target, "targetname");
	self.start = getstruct(self.end.target, "targetname");
	self.barrel = getClosestEnt(self.start.origin, getentarray ("explodable_barrel","targetname"));
	self.extra = getent(self.target, "targetname");
	self setcandamage(true);
	
	if(isdefined(self.barrel))
	{
		self.barrel.oilspill = true;
		self thread oil_spill_burn_after();
	}
	
	while(1)
	{
		self waittill("damage", other, damage, direction_vec, P, type );
		if(type == "MOD_MELEE" || type == "MOD_IMPACT")
			continue;
		
		self.damageOwner = other;
		
		playfx (level.breakables_fx["oilspill"]["spark"], P, direction_vec);
		//P = pointOnSegmentNearestToPoint(self.start.origin, self.end.origin, P);
		thread oil_spill_burn_section(P);
		self thread oil_spill_burn(P, self.start.origin);
		self thread oil_spill_burn(P, self.end.origin);
		break;
	}
	if(isdefined(self.barrel))
		self.barrel waittill("exploding");
	
	self.extra delete();
	self hide();
	
	wait 10;
	self delete();
}

getClosestEnt(org, array)
{
	if (array.size < 1)
		return;
		
//	dist = distance(array[0] getorigin(), org);
//	ent = array[0];
	dist = 256;
	ent = undefined;
	for (i=0;i<array.size;i++)
	{
		newdist = distance(array[i] getorigin(), org);
		if (newdist >= dist)
			continue;
		dist = newdist;
		ent = array[i];
	}
	return ent;
}

oil_spill_burn_after()
{
	while(1)
	{
		self.barrel waittill("damage", amount ,attacker, direction_vec, P, type);
		if(type == "MOD_MELEE" || type == "MOD_IMPACT")
			continue;
		break;
	}
	self.damageOwner = attacker;
	
	// do not pass damage owner if they have disconnected before the barrels explode
	if ( !isdefined( self.damageOwner ) ) 
		self radiusdamage (self.origin, 4, 10, 10 );
	else
		self radiusdamage (self.origin, 4, 10, 10, self.damageOwner);
}

oil_spill_burn(P, dest)
{
	
	forward = vectornormalize(dest - P);
	dist = distance(p, dest);
	range = 8;
	interval = common_scripts\utility::vector_multiply(forward, range);	
	angle = vectortoangles(forward);
	right = anglestoright(angle);
	
	barrels = getentarray ("explodable_barrel","targetname");
	distsqr = 22 * 22;
	
	test = spawn("script_origin", P);
	test hide();
	
	num = 0;
	while(1)
	{
		dist -= range;
		if(dist < range *.1)
			break;
			
		p += (interval + common_scripts\utility::vector_multiply(right, randomfloatrange(-6, 6)));		
		
		thread oil_spill_burn_section(P);
		num++;
		if(num == 4)
		{
			num = 0;
		}
		
		test.origin = P;
		
		remove = [];
		barrels = common_scripts\utility::array_removeUndefined(barrels);
		for(i=0; i<barrels.size; i++)
		{
			vec = anglestoup(barrels[i].angles);
			start = barrels[i].origin + (common_scripts\utility::vector_multiply(vec, 22));
			pos = physicstrace(start, start + (0,0,-64));
			
			if(distancesquared(P, pos) < distsqr) 
			{
				remove[remove.size] = barrels[i];
				d = (80 + randomfloat(10));
				
				if ( !isdefined ( self.damageOwner ) )
					self radiusdamage (barrels[i].origin, 4, d, d);
				else
					self radiusdamage (barrels[i].origin, 4, d, d, self.damageOwner);
				//barrels[i] dodamage(  , P);
			}
		}
		for(i=0; i<remove.size; i++)
			barrels = common_scripts\utility::array_remove(barrels, remove[i]);	
		wait .1;
	}		
	
	if(!isdefined(self.barrel))
		return;
	if( distance(P, self.start.origin) < 32)
	{
		d = (80 + randomfloat(10));
		if ( !isdefined ( self.damageOwner ) )
			self radiusdamage (self.barrel.origin, 4, d, d);
		else
			self radiusdamage (self.barrel.origin, 4, d, d, self.damageOwner);
	}
}

oil_spill_burn_section(P)
{
	count = 0;
	time = 0;
	playfx (level.breakables_fx["oilspill"]["burn"], P);
	
	while(time < 5)
	{
		if ( !isdefined ( self.damageOwner ) )
			self radiusdamage(P, 32, 5, 1);
		else
			self radiusdamage(P, 32, 5, 1, self.damageOwner);
		time += 1;
		wait 1;
	}
}

explodable_barrel_think()
{	
	if (self.classname != "script_model")
		return;
//	if ( (self.model != "com_barrel_benzin") && (self.model != "com_barrel_benzin_snow") )
//		return;
	if(!isdefined(level.precachemodeltype["com_barrel_benzin"]))
	{
		level.precachemodeltype["com_barrel_benzin"] = true;
		precacheModel("com_barrel_piece");
		precacheModel("com_barrel_piece2");	
	}
	self endon ("exploding");
	
	self breakable_clip();
	self.damageTaken = 0;
	self setcandamage(true);
	for (;;)
	{
		self waittill("damage", amount ,attacker, direction_vec, P, type);
		if(type == "MOD_MELEE" || type == "MOD_IMPACT")
			continue;
		
		self.damagetype = type;
		
		self.damageOwner = attacker;
			
		if (level.barrelExplodingThisFrame)
			wait randomfloat(1);
		self.damageTaken += amount;
		if (self.damageTaken == amount)
			self thread explodable_barrel_burn();
	}
}

explodable_barrel_burn()
{
	count = 0;
	startedfx = false;
	
	up = anglestoup(self.angles);
	worldup = anglestoup((0,90,0));
	dot = vectordot(up, worldup);
	
	offset1 = (0,0,0);
	offset2 =  common_scripts\utility::vector_multiply(up, 44);
	
	if(dot < .5)
	{
		offset1 = common_scripts\utility::vector_multiply(up, 22) - (0,0,30);
		offset2 = common_scripts\utility::vector_multiply(up, 22) + (0,0,14);	
	}
	
	if( self.damagetype != "MOD_GRENADE_SPLASH" && self.damagetype != "MOD_GRENADE" )
	{
		while (self.damageTaken < level.barrelHealth)
		{
			if (!startedfx)
			{
				playfx (level.breakables_fx["barrel"]["burn_start"], self.origin + offset1);
				startedfx = true;
			}
			if (count > 20)
				count = 0;
			
			playfx (level.breakables_fx["barrel"]["burn"], self.origin + offset2);
			
			if (count == 0)
			{
				self.damageTaken += (10 + randomfloat(10));
			}
			count++;
			wait 0.05;
		}
	}
	self thread explodable_barrel_explode();
}

explodable_barrel_explode()
{
	self notify ("exploding");
	self notify ("death");

	up = anglestoup(self.angles);
	worldup = anglestoup((0,90,0));
	dot = vectordot(up, worldup);
	
	offset = (0,0,0);
	if(dot < .5)
	{
		start = (self.origin + common_scripts\utility::vector_multiply(up, 22));
		end  = physicstrace(start, (start + (0,0,-64)));
		offset = end - self.origin;
	}
	offset += (0,0,4);
	
	self playsound (level.barrelExpSound);
	//level thread play_sound_in_space(level.barrelExpSound, self.origin);
	playfx (level.breakables_fx["barrel"]["explode"], self.origin + offset);
	
	level.barrelExplodingThisFrame = true;
	
	if (isdefined (self.remove))
	{
		self.remove delete();
	}
	
	phyExpMagnitude = 2;
	minDamage = 1;
	maxDamage = 250;
	blastRadius = 250;
	if (isdefined(self.radius))
		blastRadius = self.radius;
	
	// do not pass damage owner if they have disconnected before the barrels explode
	if ( !isdefined( self.damageOwner ) ) 
		self radiusDamage(self.origin + (0,0,30), blastRadius, maxDamage, minDamage, undefined, "MOD_EXPLOSIVE", "barrel_mp");
	else
		self radiusDamage(self.origin + (0,0,30), blastRadius, maxDamage, minDamage, self.damageOwner, "MOD_EXPLOSIVE", "barrel_mp" );
		
	physicsExplosionSphere( self.origin + (0,0,30), blastRadius, blastRadius/2, phyExpMagnitude );
	
	self maps\mp\gametypes\_shellshock::barrel_earthQuake();
		
	if (randomint(2) == 0)
		self setModel("com_barrel_piece");
	else
		self setModel("com_barrel_piece2");
	self setCanDamage( false );
	
	if(dot < .5)
	{
		start = (self.origin + common_scripts\utility::vector_multiply(up, 22));
		pos = physicstrace(start, (start + (0,0,-64)));
		
		self.origin = pos;
		self.angles += (0,0,90);
			
	}
	wait 0.05;
	level.barrelExplodingThisFrame = false;
}

getstruct(name, type)
{
	if(!isdefined(level.struct_class_names))
		return undefined;
	
	array = level.struct_class_names[type][name];
	if(!isdefined(array))
		return undefined;
	if(array.size > 1)
	{
		assertMsg ("getstruct used for more than one struct of type " + type + " called " + name +".");
		return undefined;
	}
	return array[0];
}

breakable_clip()
{
	//targeted brushmodels take priority over proximity based breakables - nate
	if (isdefined(self.target))
	{
		targ = getent(self.target,"targetname");
		if(targ.classname == "script_brushmodel")
		{
			self.remove = targ;
			return;
		}
	}
	//setup it's removable clip part
	if ((isdefined (level.breakables_clip)) && (level.breakables_clip.size > 0))
		self.remove = getClosestEnt( self.origin , level.breakables_clip );
	if (isdefined (self.remove))
		level.breakables_clip = common_scripts\utility::array_remove ( level.breakables_clip , self.remove );
}

